package com.hzw.saas.web.app.user.controller;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.hzw.saas.api.user.ICustomerService;
import com.hzw.saas.api.user.IUserAccountService;
import com.hzw.saas.api.user.bo.UserAccountBO;
import com.hzw.saas.api.user.query.UserAccountGetQuery;
import com.hzw.saas.api.user.query.UserAccountUpdateQuery;
import com.hzw.saas.common.config.annotation.SysLog;
import com.hzw.saas.common.config.util.AssertUtil;
import com.hzw.saas.common.security.pojo.dto.SaasUser;
import com.hzw.saas.common.security.token.ISaasTokenService;
import com.hzw.saas.common.security.utils.SecurityUtils;
import com.hzw.saas.common.verify.service.IVerifyService;
import com.hzw.saas.web.app.user.enums.VerifyMode;
import com.hzw.saas.web.app.user.param.EmailVerifyParam;
import com.hzw.saas.web.app.user.param.PwdForgetParam;
import com.hzw.saas.web.app.user.param.PwdResetParam;
import com.hzw.saas.web.app.user.param.SmsVerifyParam;
import io.swagger.annotations.*;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.Objects;

/**
 * 用户账户 Controller
 *
 * @author zzl
 * @since 12/22/2020
 */
@Controller
@RequestMapping("/user")
@RequiredArgsConstructor
@Api(tags = "用户中心/用户账户")
@Validated
public class UserAccountController {

    private final ICustomerService customerService;
    private final IUserAccountService userAccountService;
    private final IVerifyService verifyService;
    private final ISaasTokenService saasTokenService;

    @PutMapping("/password/forget")
    @SysLog(operation = "忘记密码", mode = 3)
    @ApiOperation(value = "忘记密码", notes = "忘记密码时使用手机号设置新密码，无需登录")
    @ApiResponses({
        @ApiResponse(code = 200, message = "重置成功,true"),
        @ApiResponse(code = 400, message = "手机号不存在/验证码错误")
    })
    @ApiOperationSort(1)
    public ResponseEntity<Boolean> forgetPassword(@Validated @RequestBody PwdForgetParam param) {
        AssertUtil.assertThrow("手机和邮箱不能同时为空", StrUtil.isAllBlank(param.getPhoneNo(), param.getEmail()));
        boolean verifySms = false;
        boolean verifyEmail = false;
        // 检查验证码
        if (StringUtils.isNotBlank(param.getPhoneNo())) {
            verifySms = verifyService.verify(param.getPhoneNo(), param.getVerifyCode());
        }
        if (StringUtils.isNotBlank(param.getEmail())) {
            verifyEmail = verifyService.verify(param.getEmail(), param.getVerifyCode());
        }
        AssertUtil.assertThrow("验证码错误", !verifySms && !verifyEmail);

        UserAccountBO userAccountBO;
        if (verifySms) {
            // 验证用户存在
            userAccountBO = userAccountService.getAccount(new UserAccountGetQuery().setPhoneNo(param.getPhoneNo()));
            AssertUtil.assertThrow("手机号不存在", userAccountBO == null);
        } else {
            // 验证用户存在
            userAccountBO = userAccountService.getAccount(new UserAccountGetQuery().setEmail(param.getEmail()));
            AssertUtil.assertThrow("邮箱不存在", userAccountBO == null);
        }
        // 更新密码
        boolean reset = userAccountService.resetPassword(userAccountBO.getUserId(), param.getPassword());
        return ResponseEntity.ok(reset);
    }

    @PutMapping("/password")
    @SysLog(operation = "修改密码", mode = 3)
    @ApiOperation(value = "修改密码", notes = "处理用户修改密码请求，用户已登录前提下，需使用邮箱或手机验证")
    @ApiResponses({
        @ApiResponse(code = 200, message = "修改成功,true"),
    })
    @ApiOperationSort(2)
    public ResponseEntity<Boolean> changePassword(@Validated @RequestBody PwdResetParam param) {
        VerifyMode verifyMode = VerifyMode.instance(param.getVerifyMode(), true);
        SaasUser saasUser = SecurityUtils.getUser();
        UserAccountBO userAccount = userAccountService.getAccount(saasUser.getUserId());
        boolean verify = false;
        switch (Objects.requireNonNull(verifyMode)) {
            case PHONE:
                verify = verifyService.verify(userAccount.getPhoneNo(), param.getVerifyCode());
                break;
            case EMAIL:
                verify = verifyService.verify(userAccount.getEmail(), param.getVerifyCode());
        }
        AssertUtil.assertThrow("验证码错误", !verify);
        boolean reset = userAccountService.resetPassword(saasUser.getUserId(), param.getPassword());
        return ResponseEntity.ok(reset);
    }

    @PutMapping("/phone")
    @SysLog(operation = "手机号新增/修改", mode = 3)
    @ApiOperation(value = "手机号新增/修改", notes = "处理用户修改手机号请求，用户已登录前提下")
    @ApiResponses({
        @ApiResponse(code = 200, message = "修改成功,true"),
        @ApiResponse(code = 400, message = "验证码错误/手机号已存在")
    })
    @ApiOperationSort(3)
    public ResponseEntity<Boolean> changePhoneNo(@Validated @RequestBody SmsVerifyParam param) {
        boolean verifySms = verifyService.verify(param.getPhoneNo(), param.getVerifyCode());
        AssertUtil.assertThrow("验证码错误", !verifySms);

        SaasUser saasUser = SecurityUtils.getUser();
        UserAccountUpdateQuery userAccount = new UserAccountUpdateQuery()
            .setUserId(saasUser.getUserId())
            .setPhoneNo(param.getPhoneNo());
        boolean updateFlag = userAccountService.updateAccount(userAccount, true);
        return ResponseEntity.ok(updateFlag);
    }

    @PutMapping("/email")
    @SysLog(operation = "邮箱新增/修改", mode = 3)
    @ApiOperation(value = "邮箱新增/修改", notes = "处理用户修改邮箱请求，用户已登录前提下")
    @ApiResponses({
        @ApiResponse(code = 200, message = "修改成功,true"),
        @ApiResponse(code = 400, message = "邮箱已存在")
    })
    @ApiOperationSort(4)
    public ResponseEntity<Boolean> changeEmail(@Validated @RequestBody EmailVerifyParam param) {
        boolean verifySms = verifyService.verify(param.getEmail(), param.getVerifyCode());
        AssertUtil.assertThrow("验证码错误", !verifySms);

        SaasUser saasUser = SecurityUtils.getUser();
        UserAccountUpdateQuery userAccount = new UserAccountUpdateQuery()
            .setUserId(saasUser.getUserId())
            .setEmail(param.getEmail());
        boolean updateFlag = userAccountService.updateAccount(userAccount, true);
        return ResponseEntity.ok(updateFlag);
    }

    @DeleteMapping("/account")
    @SysLog(operation = "注销账户", mode = 3)
    @ApiOperation(value = "注销账户", notes = "注销账户，删除用户所有数据")
    @ApiOperationSort(5)
//    public ResponseEntity<Void> deleteAccount(@Validated @RequestBody VerifyParam param) {
    public ResponseEntity<Void> deleteAccount() {
        String userId = SecurityUtils.getUserId();
        this.customerService.deleteCustomerByUserId(userId);
        this.saasTokenService.logoffToken(userId);
        return ResponseEntity.ok().build();
    }

}
